home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / util / gnu / xpdf-0.8-src.lha / xpdf-0.8-src / ltk / LTKTextIn.cc < prev    next >
C/C++ Source or Header  |  1998-11-28  |  12KB  |  488 lines

  1. //========================================================================
  2. //
  3. // LTKTextIn.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8.  
  9. #ifdef __GNUC__
  10. #pragma implementation
  11. #endif
  12.  
  13. #include <stdlib.h>
  14. #include <stdarg.h>
  15. #include <stddef.h>
  16. #include <X11/Xlib.h>
  17. #include <X11/Xutil.h>
  18. #include <X11/keysym.h>
  19. #include "gtypes.h"
  20. #include "GString.h"
  21. #include "LTKWindow.h"
  22. #include "LTKTextIn.h"
  23. #include "LTKBorder.h"
  24.  
  25. #define horizBorder 2
  26. #define vertBorder  2
  27.  
  28. LTKTextIn::LTKTextIn(char *name1, int widgetNum1, int minWidth1,
  29.              char *fontName1, LTKStringValCbk doneCbk1,
  30.              char *tabTarget1):
  31.     LTKWidget(name1, widgetNum1) {
  32.   minWidth = minWidth1;
  33.   text = new GString();
  34.   active = gFalse;
  35.   firstChar = 0;
  36.   cursor = 0;
  37.   selectionEnd = 0;
  38.   dragging = gFalse;
  39.   doneCbk = doneCbk1;
  40.   tabTarget = tabTarget1;
  41.   fontName = fontName1;
  42.   fontStruct = NULL;
  43.   textGC = None;
  44. }
  45.  
  46. LTKTextIn::~LTKTextIn() {
  47.   delete text;
  48.   if (fontName && fontStruct) {
  49.     XFreeFont(getDisplay(), fontStruct);
  50.     XFreeGC(getDisplay(), textGC);
  51.   }
  52. }
  53.  
  54. long LTKTextIn::getEventMask() {
  55.   return LTKWidget::getEventMask() |
  56.          ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
  57.          PointerMotionHintMask | KeyPressMask;
  58. }
  59.  
  60. void LTKTextIn::setText(char *s) {
  61.   delete text;
  62.   text = new GString(s);
  63.   firstChar = 0;
  64.   if (getXWindow() != None && active)
  65.     xorCursor();
  66.   cursor = selectionEnd = 0;
  67.   if (getXWindow() != None) {
  68.     redrawTail(0);
  69.     if (active)
  70.       xorCursor();
  71.   }
  72. }
  73.  
  74. void LTKTextIn::layout1() {
  75.   XGCValues gcValues;
  76.  
  77.   if (textGC == None) {
  78.     if (fontName &&
  79.     (fontStruct = XLoadQueryFont(getDisplay(), fontName))) {
  80.       XGetGCValues(getDisplay(), getFgGC(),
  81.            GCForeground | GCBackground | GCGraphicsExposures,
  82.            &gcValues);
  83.       gcValues.font = fontStruct->fid;
  84.       textGC = XCreateGC(getDisplay(), parent->getXWindow(),
  85.              GCForeground | GCBackground | GCGraphicsExposures |
  86.              GCFont, &gcValues);
  87.     } else {
  88.       fontName = NULL;
  89.       fontStruct = parent->getXFontStruct();
  90.       textGC = getFgGC();
  91.     }
  92.   }
  93.   textHeight = fontStruct->ascent + fontStruct->descent;
  94.   textBase = fontStruct->ascent;
  95.   width = minWidth * fontStruct->max_bounds.width + 2 * horizBorder + 1;
  96.   height = textHeight + 2 * vertBorder;
  97. }
  98.  
  99. void LTKTextIn::layout3() {
  100.   XRectangle rect;
  101.  
  102.   LTKWidget::layout3();
  103.   rect.x = horizBorder - 1;   // need one pixel in left border for cursor
  104.   rect.y = 0;
  105.   rect.width = width - 2 * horizBorder + 1;
  106.   rect.height = height;
  107.   XSetClipRectangles(getDisplay(), textGC, 0, 0, &rect, 1, Unsorted);
  108. }
  109.  
  110. void LTKTextIn::redraw() {
  111.   XFillRectangle(getDisplay(), xwin, getBgGC(), 0, 0, width, height);
  112.   redrawTail(firstChar);
  113.   if (active)
  114.     xorCursor();
  115. }
  116.  
  117. void LTKTextIn::buttonPress(int mx, int my, int button, GBool dblClick) {
  118.   // move cursor
  119.   if (button == 1) {
  120.     xorCursor();
  121.     cursor = xToCursor(mx);
  122.     if (cursor < firstChar)
  123.       cursor = firstChar;
  124.     selectionEnd = cursor;
  125.     xorCursor();
  126.     dragging = gTrue;
  127.     dragAnchor = cursor;
  128.  
  129.   // paste
  130.   } else if (button == 2) {
  131.     parent->requestPaste(this);
  132.   }
  133. }
  134.  
  135. void LTKTextIn::buttonRelease(int mx, int my, int button, GBool click) {
  136.   dragging = gFalse;
  137.   if (cursor != selectionEnd)
  138.     parent->setSelection(this, new GString(text->getCString() + cursor,
  139.                        selectionEnd - cursor));
  140. }
  141.  
  142. void LTKTextIn::mouseMove(int mx, int my, int btn) {
  143.   int newCursor, newSelectionEnd;
  144.   int i;
  145.  
  146.   if (dragging) {
  147.     i = xToCursor(mx);
  148.     if (i >= dragAnchor) {
  149.       newCursor = dragAnchor;
  150.       newSelectionEnd = i;
  151.     } else {
  152.       newCursor = i;
  153.       newSelectionEnd = dragAnchor;
  154.     }
  155.     if (newCursor != cursor || newSelectionEnd != selectionEnd)
  156.       moveCursor(newCursor, newSelectionEnd, i);
  157.   }
  158. }
  159.  
  160. void LTKTextIn::activate(GBool on) {
  161.   if (active != on) {
  162.     if (on) {
  163.       xorCursor();
  164.       parent->setKeyWidget(this);
  165.       active = gTrue;
  166.     } else {
  167.       xorCursor();
  168.       selectionEnd = cursor;
  169.       parent->setKeyWidget(NULL);
  170.       active = gFalse;
  171.       if (doneCbk)
  172.     (*doneCbk)(this, widgetNum, text);
  173.     }
  174.   }
  175. }
  176.  
  177. void LTKTextIn::keyPress(KeySym key, Guint modifiers, char *s, int n) {
  178.   int newCursor, newSelectionEnd;
  179.   int redrawPos;
  180.   GBool killSelection;
  181.   LTKWidget *widget;
  182.  
  183.   newCursor = cursor;
  184.   killSelection = gTrue;
  185.   redrawPos = -1;
  186.   if (key == XK_Left) {        // left arrow
  187.     if (cursor > 0)
  188.       --newCursor;
  189.   } else if (key == XK_Right) {    // right arrow
  190.     if (cursor < text->getLength())
  191.       ++newCursor;
  192.   } else if (n >= 1) {
  193.     switch (s[0]) {
  194.     case '\001':        // ^A
  195.       newCursor = 0;
  196.       break;
  197.     case '\002':        // ^B
  198.       if (cursor > 0)
  199.     --newCursor;
  200.       break;
  201.     case '\005':        // ^E
  202.       newCursor = text->getLength();
  203.       break;
  204.     case '\006':        // ^F
  205.       if (cursor < text->getLength())
  206.     ++newCursor;
  207.       break;
  208.     case '\014':        // ^L
  209.       redrawPos = firstChar;
  210.       killSelection = gFalse;
  211.       break;
  212.     case '\b':            // bs
  213.     case '\177':        // del
  214.       if (selectionEnd > cursor) {
  215.     text->del(cursor, selectionEnd - cursor);
  216.     redrawPos = cursor;
  217.       } else if (cursor > 0) {
  218.     text->del(cursor - 1);
  219.     --newCursor;
  220.     redrawPos = newCursor;
  221.       }
  222.       break;
  223.     case '\004':        // ^D
  224.       if (selectionEnd > cursor) {
  225.     text->del(cursor, selectionEnd - cursor);
  226.     redrawPos = cursor;
  227.       } else if (cursor < text->getLength()) {
  228.     text->del(cursor);
  229.     redrawPos = cursor;
  230.       }
  231.       break;
  232.     case '\013':        // ^K
  233.       text->del(cursor, text->getLength() - cursor);
  234.       redrawPos = cursor;
  235.       break;
  236.     case '\025':        // ^U
  237.       text->clear();
  238.       newCursor = 0;
  239.       redrawPos = newCursor;
  240.       break;
  241.     case '\n':            // return, tab
  242.     case '\r':
  243.     case '\t':
  244.       activate(gFalse);
  245.       if (tabTarget)
  246.     if ((widget = parent->findWidget(tabTarget)))
  247.       widget->activate(gTrue);
  248.       newCursor = newSelectionEnd = cursor;
  249.       break;
  250.     default:            // insert char
  251.       if (s[0] >= 0x20) {
  252.     if (selectionEnd > cursor)
  253.       text->del(cursor, selectionEnd - cursor);
  254.     text->insert(cursor, s);
  255.     redrawPos = cursor;
  256.     ++newCursor;
  257.       }
  258.       break;
  259.     }
  260.   } else {            // ignore weird X keysyms
  261.     killSelection = gFalse;
  262.   }
  263.  
  264.   newSelectionEnd = killSelection ? newCursor : selectionEnd;
  265.   if (newCursor != cursor || newSelectionEnd != selectionEnd ||
  266.       redrawPos >= 0) {
  267.     xorCursor();
  268.     cursor = newCursor;
  269.     selectionEnd = newSelectionEnd;
  270.     redrawTail(redrawPos);
  271.     if (active)
  272.       xorCursor();
  273.   }
  274. }
  275.  
  276. void LTKTextIn::clearSelection() {
  277.   if (active)
  278.     xorCursor();
  279.   selectionEnd = cursor;
  280.   if (active)
  281.     xorCursor();
  282. }
  283.  
  284. void LTKTextIn::paste(GString *str) {
  285.   int redrawPos;
  286.  
  287.   if (active)
  288.     xorCursor();
  289.   text->insert(cursor, str);
  290.   redrawPos = cursor;
  291.   cursor += str->getLength();
  292.   selectionEnd = cursor;
  293.   redrawTail(redrawPos);
  294.   if (active)
  295.     xorCursor();
  296. }
  297.  
  298. int LTKTextIn::xToCursor(int mx) {
  299.   XCharStruct extents;
  300.   int direction, ascent, descent;
  301.   int x1, x2;
  302.   int pos;
  303.  
  304.   if (mx < horizBorder)
  305.     return firstChar > 0 ? firstChar - 1 : 0;
  306.  
  307.   x2 = horizBorder;
  308.   for (pos = firstChar; pos < text->getLength(); ++pos) {
  309.     XTextExtents(fontStruct, text->getCString() + pos, 1,
  310.          &direction, &ascent, &descent, &extents);
  311.     x1 = x2;
  312.     x2 += extents.width;
  313.     if (mx < (x1 + x2) / 2)
  314.       break;
  315.   }
  316.   return pos;
  317. }
  318.  
  319. int LTKTextIn::cursorToX(int cur) {
  320.   XCharStruct extents;
  321.   int direction, ascent, descent;
  322.   int x;
  323.  
  324.   x = horizBorder;
  325.   if (cur > firstChar) {
  326.     XTextExtents(fontStruct, text->getCString() + firstChar,
  327.          cur - firstChar,
  328.          &direction, &ascent, &descent, &extents);
  329.     x += extents.width;
  330.   }
  331.   return x;
  332. }
  333.  
  334. void LTKTextIn::xorCursor() {
  335.   int tx1, tx2, ty;
  336.   int i, j;
  337.  
  338.   ty = (height - textHeight) / 2;
  339.  
  340.   // draw cursor
  341.   if (cursor == selectionEnd) {
  342.     tx1 = cursorToX(cursor);
  343.     XDrawLine(getDisplay(), xwin, getXorGC(),
  344.           tx1 - 1, ty, tx1 - 1, ty + textHeight - 1);
  345.     XDrawLine(getDisplay(), xwin, getXorGC(),
  346.           tx1, ty, tx1, ty + textHeight - 1);
  347.  
  348.   // draw selection
  349.   } else {
  350.     i = (cursor >= firstChar) ? cursor : firstChar;
  351.     tx1 = cursorToX(